home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ShareWare OnLine 2
/
ShareWare OnLine Volume 2 (CMS Software)(1993).iso
/
os2
/
which100.zip
/
WHICH.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-03-12
|
6KB
|
217 lines
/*---------------------------------------------------------------------------
which.c last revised: 12 Mar 93
Program to find path of an executable command under either OS/2 or
(possibly) MS-DOS. Not a lot of error-checking, but the array sizes
are reasonably generous.
Copyright (c) 1993 by Greg Roelofs. You may use this code for any pur-
pose whatsoever, as long as you don't sell it and don't claim to have
written it. Not that you'd want to.
---------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifndef TRUE
# define TRUE 1
# define FALSE 0
#endif
#if defined(__OS2__) && !defined(OS2)
# define OS2
#endif
#if defined(__IBMC__)
# define S_IFMT 0xF000 /* or (S_IFREG | S_IFDIR | S_IFCHR) */
#endif
#ifndef S_ISDIR
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
#ifdef DEBUG
# define Trace(x) fprintf x
#else
# define Trace(x)
#endif
struct stat statbuf;
#ifdef OS2
static char *OS = "OS/2";
#else
static char *OS = "MS-DOS";
#endif
/* extensions must be in order of operating-system precedence! */
static char *ext[] = {
".com",
".exe",
#ifdef OS2
".cmd",
#endif
".bat"
};
/* OS/2 internal commands: some of these are rarely used outside of
* command files, but all of them can be called from the command line.
* Technically I guess they're cmd.exe commands; 4OS2 presumably has
* other "internal OS/2 commands" which aren't included here. (I may
* have screwed up in other ways, so if you find errors, let me know.
* I also don't know if some of the OS/2-only commands might be in later
* versions of MS-DOS...I suppose a better way to do this would be to
* use system() and check the errors, but that can wait for some other
* time.)
*/
static char *internal[] = {
#ifdef OS2
"chcp",
"detach",
"dpath",
"endlocal",
"extproc",
"keys",
"move",
"setlocal",
"start",
#endif
"call",
"cd",
"chdir",
"cls",
"copy",
"date",
"del",
"dir",
"echo",
"erase",
"exit",
"for",
"goto",
"if",
"md",
"mkdir",
"path",
"pause",
"prompt",
"rd",
"rem",
"ren",
"rename",
"rmdir",
"set",
"shift",
"time",
"type",
"ver",
"verify",
"vol"
};
int main(int argc, char *argv[])
{
char *prognam, *p, *q, *path, *dir[1000], tempname[300];
int i, j, k, numdirs=0;
int numexts = sizeof(ext)/sizeof(char *);
int numinternal = sizeof(internal)/sizeof(char *);
prognam = argv[0];
/* check for arguments; exit if none */
if (argc < 2) {
fprintf(stderr, "%s: too few arguments\n", prognam);
fprintf(stderr, "usage: which cmd [cmd ...]\n");
exit(1);
}
++argv;
--argc;
/* current directory is always implied, even if no path */
dir[numdirs++] = ".";
/* terminate path elements and store pointers to each directory */
if ((path = getenv("PATH")) == (char *)NULL || *path == '\0') {
Trace((stderr, "\nPATH is empty\n\n"));
} else {
Trace((stderr, "\nPATH = %s\n\n", path));
if (*path != ';')
dir[numdirs++] = path;
p = path - 1;
while (*++p)
if (*p == ';') {
*p = '\0';
if ((p[1] != '\0') && (p[1] != ';'))
dir[numdirs++] = p + 1;
} else
*p = tolower(*p); /* should probably make this an option... */
}
/* for each command given as an argument, check all of the directories
* in the path: first see if it's an internal command; if not, see if
* the OS will consider it a command as is (has a dot), and if so whether
* it exists; then try appending each extension (in order of precedence)
* and again check for existence in each path directory
*/
for (j = 0; j < argc; ++j) {
int hasdot, found=FALSE;
/* don't bother with internal commands if has a dot */
if (!(hasdot = (strchr(argv[j], (int)'.') != (char *)NULL))) {
for (i = 0; (i < numinternal) && !found; ++i) {
Trace((stderr, "checking %s\n", internal[i]));
if (stricmp(argv[j], internal[i]) == 0) {
found = TRUE;
printf("%s: %s command-shell internal command\n",
argv[j], OS);
break;
}
}
}
for (i = 0; (i < numdirs) && !found; ++i) {
p = tempname;
q = dir[i];
while (*p++ = *q++); /* p now points to char *after* '\0' */
p[-1] = '\\'; /* replace null */
q = argv[j];
while (*p++ = *q++); /* copy program name */
--p; /* point at null */
if (hasdot) {
Trace((stderr, "checking %s\n", tempname));
if (!stat(tempname, &statbuf) && !S_ISDIR(statbuf.st_mode)) {
found = TRUE;
printf("%s\n", tempname);
break;
}
}
for (k = 0; (k < numexts) && !found; ++k) {
strcpy(p, ext[k]);
Trace((stderr, "checking %s\n", tempname));
if (!stat(tempname, &statbuf) && !S_ISDIR(statbuf.st_mode)) {
found = TRUE;
printf("%s\n", tempname);
break;
}
}
} /* end i-loop */
if (!found) {
printf("no %s in", argv[j]);
for (i = 0; i < numdirs; ++i)
printf(" %s", dir[i]);
printf("\n");
}
}
return 0;
}